//
// Created by bianzheng on 2022/6/14.
//

#ifndef REC2_MIPS_CONVERTRATINGS_HPP
#define REC2_MIPS_CONVERTRATINGS_HPP

#include <unordered_map>
#include <string>
#include <vector>

namespace Rec2MIPS {
    class RatingString {
    public:
        std::string userID_, itemID_, rating_;

        RatingString() = default;

        RatingString(const std::string &userID, const std::string &itemID, const std::string &rating) {
            this->userID_ = userID;
            this->itemID_ = itemID;
            this->rating_ = rating;
        }
    };

    class RatingNum {
    public:
        int userID_, itemID_;
        double rating_;

        RatingNum() = default;

        RatingNum(const int &userID, const int &itemID, const double &rating) {
            this->userID_ = userID;
            this->itemID_ = itemID;
            this->rating_ = rating;
        }
    };

    std::pair<int, int> ConvertRatings(const std::vector<RatingString> &input_l,
                        std::vector<RatingNum> &output_l) {
        output_l.clear();
        std::unordered_map<std::string, int> item_rating_m;
        std::unordered_map<std::string, int> user_rating_m;

        const size_t n_rating = input_l.size();
        int user_idx = 1;
        int item_idx = 1;
        for (size_t ratingID = 0; ratingID < n_rating; ratingID++) {
            const std::string &itemID = input_l[ratingID].itemID_;

            if (item_rating_m.find(itemID) == item_rating_m.end()) { // not find
                item_rating_m[itemID] = item_idx;
                item_idx++;
            }

            const std::string &userID = input_l[ratingID].userID_;
            if (user_rating_m.find(userID) == user_rating_m.end()) { // not find
                user_rating_m[userID] = user_idx;
                user_idx++;
            }
        }

        for (size_t ratingID = 0; ratingID < n_rating; ratingID++) {
            std::string itemID_str = input_l[ratingID].itemID_;
            std::string userID_str = input_l[ratingID].userID_;
            std::string rating_str = input_l[ratingID].rating_;

            int itemID_num = item_rating_m[itemID_str];
            int userID_num = user_rating_m[userID_str];
            double rating_num = std::atof(rating_str.c_str());

            output_l.emplace_back(userID_num, itemID_num, rating_num);
        }
        return std::make_pair(user_idx, item_idx);
    }
}
#endif //REC2_MIPS_CONVERTRATINGS_HPP
